英雄列表範例已經初步展示過 Listbox 的用法,你應該可以觀察到它的架構也可分成 MVC三個角色,Listbox 會根據你所指定的資料物件來繪製子元件 Listitem,當你呼叫 ListModel的 method 來變更資料量的時候(如 add()
, remove()
, clearAll()
),ListModel 內部會通知 Listbox 並更新畫面。
ZK 支援直接在 zul 中定義元件與子元件,這是「靜態產生」元件,例如:
<listbox id="box">
<listhead sizable="true">
<listheader label="name" sort="auto" />
<listheader label="gender" sort="auto" />
</listhead>
<listitem>
<listcell label="Mary" />
<listcell label="FEMALE" />
</listitem>
<listitem>
<listcell label="John" />
<listcell label="MALE" />
</listitem>
<listitem>
<listcell label="Jane" />
<listcell label="FEMALE" />
</listitem>
<listitem>
<listcell label="Henry" />
<listcell label="MALE" />
</listitem>
</listbox>
而「動態產生」元件就是要創造一個 ListModelList
給元件,雖然兩種方法產生的元件功能相同,不過內部運作稍有不同。主要的差別在於:「狀態儲存的位置不同:資料驅動繪製的元件,狀態儲存與控制都在資料模型 (ListModel
),而靜態產生的狀態是存在元件中」
以 Listbox 為例,資料驅動繪製的狀況下,要取得被選擇的項目是要從 ListModelList
中取得:
model.getSelection(); //回傳資料物件如 Hero
Listbox.getSelectedItem()
回傳的是被選擇的 Listitem
,而不是資料。
用 Java 選擇項目也一樣:
model.addToSelection(hero); //傳入資料物件而不是 Listitem
如果要啟用多選模式,也是呼叫 ListModelList.setMultiple(true)
而不是元件上 Listbox.setMultiple()
String[] names = {"Mary", "John", "Jane", "Henry"};
ListModelList model = new ListModelList(names);
model.setMultiple(true);
在 ZK 的元件中,許多元件都支援這樣的特性,不過他們可以支援的 model 類別不同。
先前英雄列表範例中提到用 <template>
定義繪製的範本,但如果你要在執行期根據各種情況來繪製時怎麼辦呢?對應 <template>
的 Java 作法就是實作繪製器介面,不同的元件需要實作不同的介面,如 Listbox
需要實作 ListitemRenderer
,範例如下:
public class MyRenderer implements ListitemRenderer{
public void render(Listitem listitem, Object data, int index) {
Listcell cell =new Listcell();
listitem.appendChild(cell);
if (datainstanceof String[]){
cell.appendChild(new Label(((String[])data)[0].toString()));
}elseif (datainstanceof String){
cell.appendChild(new Label(data.toString()));
}else {
cell.appendChild(new Label("UNKNOW:"+data.toString()));
}
}
}
實作完成後,可透過 透過 Listbox.setItemRenderer(String)
來指派,或是
<listbox itemRender="quickstart.MyRenderer"/>